from main.exceptions.exception import PhysicalMemoryException
from abc import ABCMeta, abstractmethod

    


class Physical(object):
    
    __metaclass__ = ABCMeta
    
    @abstractmethod
    def memory_type(self):
        raise NotImplemented()

    def __init__(self, size=None):
        self.__size = size or 1000;
        self.__data = [0]*self.__size
        
    def load(self, data, start, end):
        self.safe_load(data, start, end)
        
    def unsafe_load(self, data, start, end):       
        self.__temp_index = 0
        last = end - start
        while self.__temp_index <= last:
            self.data[start+self.__temp_index] = data[self.__temp_index]           
            self.__temp_index += 1
        
    def safe_load(self, data, start, end):
        if(start >= end):
            raise PhysicalMemoryException(self.type + " incorrect range " + str(start) + ".." + str(end))
        if(end > self.size ):
            raise PhysicalMemoryException(self.type + "  - trying to load on nonexistent address. range: " + str(start) + ".." + str(end) + ", [memory size: " + str(self.size) + "]")
        try:
            self.unsafe_load(data, start, end)
        except IndexError:
            raise PhysicalMemoryException(self.type + "  - can not load from source index " + str(self.__temp_index))
        
    def get(self, address):
        if(address > self.size ):
            raise PhysicalMemoryException(self.type + "  - trying to get a nonexistent address " + address + "[size: " + self.size + "]")
        return self.data[address]
    
    @property
    def type(self):
        return self.memory_type()
    
    @property
    def size(self):
        return self.__size

    @property
    def data(self):
        return self.__data

